package com.wit.witmg.config;

import com.wit.witmg.entity.DeviceSession;
import com.wit.witmg.entity.TMonitDust;
import com.wit.witmg.entity.Tefdata;
import com.wit.witmg.service.ITMonitDustService;
import com.wit.witmg.service.ITefdataService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;

@Component
@RequiredArgsConstructor
public class DustTcpServer implements CommandLineRunner, DisposableBean {
    //粉尘TCP服务器
    final ITMonitDustService monitDustService;

    // 配置参数
    private static final int PORT = 2405;
    private static final int MAX_THREADS = 100;
    private static final int HEARTBEAT_INTERVAL = 30; // 心跳间隔(秒)
    private static final int RECONNECT_WAIT_TIME = 5000; // 客户端重连等待时间(毫秒)

    // 连接管理
    private final ConcurrentMap<Integer, DeviceSession> activeSessions = new ConcurrentHashMap<>();
    private ServerSocket serverSocket;
    private ExecutorService threadPool;
    private ScheduledExecutorService scheduler;
    private volatile boolean isRunning = true;

    @Override
    public void run(String... args) throws Exception {
        startTcpServer();
    }

    @Override
    public void destroy() throws Exception {
        // Spring容器关闭时优雅停止服务
        stopTcpServer();
    }

    private void startTcpServer() {
        threadPool = Executors.newFixedThreadPool(MAX_THREADS);
        scheduler = Executors.newScheduledThreadPool(1);

        try {
            serverSocket = new ServerSocket(PORT);
            System.out.printf("TCP服务器已启动，监听端口: %d\n", PORT);

            // 独立线程处理客户端连接
            new Thread(() -> {
                while (isRunning) {
                    try {
                        Socket clientSocket = serverSocket.accept();
                        threadPool.execute(() -> handleClient(clientSocket));
                    } catch (IOException e) {
                        if (isRunning) {
                            System.err.println("接受客户端连接异常: " + e.getMessage());
                        }
                    }
                }
            }).start();

//            startHeartbeatCheck();
        } catch (IOException e) {
            System.err.println("TCP服务器启动失败: " + e.getMessage());
            throw new RuntimeException("TCP服务器启动失败", e);
        }
    }

    private void stopTcpServer() {
        isRunning = false;

        // 关闭所有客户端连接
        activeSessions.forEach((id, session) -> {
            try {
                session.getSocket().close();
            } catch (IOException e) {
                System.err.println("关闭客户端连接异常: " + e.getMessage());
            }
        });
        activeSessions.clear();

        // 关闭线程池
        if (threadPool != null) {
            threadPool.shutdownNow();
        }
        if (scheduler != null) {
            scheduler.shutdownNow();
        }

        // 关闭服务器Socket
        if (serverSocket != null) {
            try {
                serverSocket.close();
            } catch (IOException e) {
                System.err.println("关闭服务器Socket异常: " + e.getMessage());
            }
        }

        System.out.println("TCP服务器已停止");
    }

    private void handleClient(Socket socket) {
        String clientIp = socket.getInetAddress().getHostAddress();
        System.out.printf("新连接来自: %s\n", clientIp);
        try (InputStream in = socket.getInputStream();
             PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {

            byte[] buffer = new byte[1024]; // 缓冲区大小可根据实际情况调整
            int bytesRead;

            while ((bytesRead = in.read(buffer)) != -1) {
                String receivedData = new String(buffer, 0, bytesRead).trim();
//                System.out.println("收到数据（HEX）: " + bytesToHex(buffer, bytesRead));
                System.out.println("收到数据（ASCII）: " + receivedData);

                // 检查是否是特定指令 "108B00008B16"
                if (receivedData.contains("108B00008B16")) {
                    // 回复 "1049FFFF4716"（按需调整编码方式）
                    out.println("1049FFFF4716\r\n");
//                    out.flush();
                    System.out.println("发送响应（HEX）: 1049FFFF4716");
                    continue; // 跳过后续处理
                }

                // 其他数据尝试解析并存入数据库
                try {
                    TMonitDust t = parseString(receivedData);
                    if (t != null) {
                        monitDustService.save(t);
                        System.out.println("数据已保存到数据库");

                        if(t.getSid()!=null && t.getSid()>0){
                            DeviceSession session = new DeviceSession(t.getSid().intValue(),socket,out);
                            activeSessions.put(t.getSid().intValue(), session);
                            monitDustService.addConnection(t.getSid().intValue(), session);
                            monitDustService.handleDeviceMessage(t.getSid().intValue(), receivedData);
                        }
                    }

                    // 发送通用响应 "1000FFFFFE"（按需调整编码方式）
//                    byte[] generalResponse = hexStringToByteArray("1000FFFFFE");
                    out.println("1000FFFFFE\r\n");
                    System.out.println("发送通用响应（HEX）: 1000FFFFFE");
                } catch (Exception e) {
                    System.err.println("数据处理异常: " + e.getMessage());
                }
            }
        } catch (IOException e) {
            System.err.println("客户端处理异常: " + e.getMessage());
        }

    }

    // 辅助方法：字节数组转HEX字符串（用于日志）
//    private String bytesToHex(byte[] bytes, int length) {
//        StringBuilder hexString = new StringBuilder();
//        for (int i = 0; i < length; i++) {
//            hexString.append(String.format("%02X", bytes[i]));
//        }
//        return hexString.toString();
//    }
//
//    // 辅助方法：HEX字符串转字节数组（用于发送响应）
//    private byte[] hexStringToByteArray(String hex) {
//        int len = hex.length();
//        byte[] data = new byte[len / 2];
//        for (int i = 0; i < len; i += 2) {
//            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
//                    + Character.digit(hex.charAt(i + 1), 16));
//        }
//        return data;
//    }

    public TMonitDust parseString(String input) {
        if (input == null || input.isEmpty()) {
            return null;
        }
        //001B774168BBE8A00001

        TMonitDust t = new TMonitDust();
        // 提取前8位作为设备ID并转换为16进制字符串
        t.setData(input);
        String deviceIdHex = input.substring(0, 8);
        long deviceId = Long.parseLong(deviceIdHex, 16);
        t.setSid(deviceId);

        String timestampStr = input.substring(8, 16);
        try {
            // 将16进制时间戳转换为十进制数值
            long timestamp = Long.parseLong(timestampStr, 16);
            t.setDate(timestamp);
        } catch (NumberFormatException e) {
            System.err.println("时间戳格式错误: " + timestampStr);
            t.setDate(null);
        }
        try {
            double dust = Long.parseLong(input.substring(16),16);
            t.setDust(dust);
        }catch (Exception e){}
        return t;
    }



    // 增强版心跳检测
//    private void startHeartbeatCheck() {
//        scheduler.scheduleAtFixedRate(() -> {
//            long now = System.currentTimeMillis();
//            activeSessions.entrySet().removeIf(entry -> {
//                DeviceSession session = entry.getValue();
//                if (now - session.getLastActiveTime() > HEARTBEAT_INTERVAL * 1000) {
//                    try {
//                        // 发送心跳检测
////                        session.getWriter().println("HEARTBEAT_CHECK");
//                        // 检查连接是否仍然活跃
//                        if (session.getSocket().isClosed() || !session.getSocket().isConnected()) {
//                            tcpCommandService.removeConnection(entry.getKey());
//                            return true; // 移除无效连接
//                        }
//                    } catch (Exception e) {
//                        System.out.println("心跳检测失败，设备断开: " + entry.getKey());
//                        tcpCommandService.removeConnection(entry.getKey());
//                        return true; // 移除无效连接
//                    }
//                }
//                return false;
//            });
//        }, HEARTBEAT_INTERVAL, HEARTBEAT_INTERVAL, TimeUnit.SECONDS);
//    }

    // 管理控制台
//    private void startAdminConsole() {
//        new Thread(() -> {
//            Scanner scanner = new Scanner(System.in);
//            while (true) {
//                System.out.print("Server> ");
//                String cmd = scanner.nextLine().trim();
//
//                if (cmd.equals("list")) {
//                    System.out.println("Connected devices (" +
//                            activeSessions.size() + "):");
//                    activeSessions.forEach((id, session) ->
//                            System.out.printf("- %s (IP: %s, Active: %ds ago)\n",
//                                    id,
//                                    session.socket.getInetAddress(),
//                                    (System.currentTimeMillis() - session.lastActiveTime)/1000
//                            )
//                    );
//                } else if (cmd.startsWith("kick ")) {
//                    String deviceId = cmd.substring(5);
//                    DeviceSession session = activeSessions.get(deviceId);
//                    if (session != null) {
//                        try {
//                            session.socket.close();
//                            System.out.println("Device kicked: " + deviceId);
//                        } catch (IOException e) {
//                            e.printStackTrace();
//                        }
//                    }
//                }
//            }
//        }).start();
//    }

    // 根据Socket查找设备ID
//    private String findDeviceIdBySocket(Socket socket) {
//        for (Map.Entry<String, DeviceSession> entry : activeSessions.entrySet()) {
//            if (entry.getValue().socket == socket) {
//                return entry.getKey();
//            }
//        }
//        return null;
//    }


}